package com.desmond.squarecamera;

import com.desmond.squarecamera.util.Base64;
import com.desmond.squarecamera.util.BitmapUtil;
import com.desmond.squarecamera.util.ThumbnailUtils;
import ohos.aafwk.ability.DataAbilityHelper;
import ohos.agp.utils.Matrix;
import ohos.agp.window.service.Display;
import ohos.agp.window.service.DisplayAttributes;
import ohos.agp.window.service.DisplayManager;
import ohos.app.Context;
import ohos.data.rdb.ValuesBucket;
import ohos.media.image.ImagePacker;
import ohos.media.image.ImageSource;
import ohos.media.image.PixelMap;
import ohos.media.image.common.Size;
import ohos.media.photokit.common.AVLogCompletedListener;
import ohos.media.photokit.metadata.AVLoggerConnection;
import ohos.media.photokit.metadata.AVStorage;
import ohos.utils.net.Uri;

import java.io.*;
import java.text.SimpleDateFormat;
import java.util.Date;

public class ImageUtility {

    public static String convertBitmapToString(PixelMap pixelMap) {
        ByteArrayOutputStream out = new ByteArrayOutputStream();

        BitmapUtil.compress(pixelMap, "image/jpeg", 80, out);

        return Base64.encodeToString(out.toByteArray(), Base64.DEFAULT);
    }

    public static byte[] convertBitmapStringToByteArray(String bitmapByteString) {
        return Base64.decode(bitmapByteString, Base64.DEFAULT);
    }

    public static PixelMap rotatePicture(Context context, int rotation, byte[] data) {

        PixelMap pixelMap = decodeSampledBitmapFromByte(context, data);

        if (rotation != 0) {
            PixelMap oldPixelMap = pixelMap;
            Matrix matrix = new Matrix();
            matrix.postRotate(rotation);

            int width = oldPixelMap.getImageInfo().size.width;
            int height = oldPixelMap.getImageInfo().size.height;

            pixelMap = BitmapUtil.createPixelMap(
                    oldPixelMap, 0, 0, width, height, matrix, false);

            oldPixelMap.release();
        }

        return pixelMap;
    }

    public static Uri savePicture(Context context, PixelMap pixelMap) {
        try {

            int cropHeight;
            int width = pixelMap.getImageInfo().size.width;
            int height = pixelMap.getImageInfo().size.height;
            if (height > width) {
                cropHeight = width;
            } else {
                cropHeight = height;
            }

            pixelMap = ThumbnailUtils.extractThumbnail(pixelMap,
                    cropHeight,
                    cropHeight,
                    ThumbnailUtils.OPTIONS_RECYCLE_INPUT);

            String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
            String fileName = "IMG_" + timeStamp + ".jpg";

            ValuesBucket valuesBucket = new ValuesBucket();
            valuesBucket.putString(AVStorage.Images.Media.DISPLAY_NAME, fileName);
            valuesBucket.putString("relative_path", "DCIM/Camera");
            valuesBucket.putString(AVStorage.Images.Media.MIME_TYPE, "image/JPEG");
            //应用独占
            valuesBucket.putInteger("is_pending", 1);
            DataAbilityHelper helper = DataAbilityHelper.creator(context);
            int id = helper.insert(AVStorage.Images.Media.EXTERNAL_DATA_ABILITY_URI, valuesBucket);
            Uri uri = Uri.appendEncodedPathToUri(AVStorage
                    .Images.Media
                    .EXTERNAL_DATA_ABILITY_URI,
                    String.valueOf(id));
            //这里需要"w"写权限
            FileDescriptor fd = helper.openFile(uri, "w");
            ImagePacker imagePacker = ImagePacker.create();
            ImagePacker.PackingOptions packingOptions = new ImagePacker.PackingOptions();
            OutputStream outputStream = new FileOutputStream(fd);
            packingOptions.format = "image/jpeg";
            packingOptions.quality = 90;
            boolean result = imagePacker.initializePacking(outputStream, packingOptions);
            if (result) {
                result = imagePacker.addImage(pixelMap);
                if (result) {
                    long dataSize = imagePacker.finalizePacking();
                }
            }
            outputStream.flush();
            outputStream.close();
            valuesBucket.clear();
            //解除独占
            valuesBucket.putInteger("is_pending", 0);
            helper.update(uri, valuesBucket, null);

            return uri;
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("=== : error : " + e.getMessage());
        }
        return null;
    }

    public static PixelMap decodeSampledBitmapFromPath(String path, int reqWidth, int reqHeight) {
        final ImageSource.DecodingOptions options = new ImageSource.DecodingOptions();

        File file = new File(path);
        ImageSource.SourceOptions sourceOptions = new ImageSource.SourceOptions();
        sourceOptions.formatHint = "image/jpeg";
        ImageSource imageSource = ImageSource.create(file, sourceOptions);

        ImageSource.DecodingOptions decodingOpts = new ImageSource.DecodingOptions();
        Size size = imageSource.getImageInfo().size;

        decodingOpts.sampleSize = calculateInSampleSize(size, reqWidth, reqHeight);
        PixelMap pixelMap = imageSource.createPixelmap(decodingOpts);
        imageSource.release();
        return pixelMap;
    }

    public static PixelMap decodeSampledBitmapFromByte(Context context, byte[] bitmapBytes) {

        Display display = DisplayManager.getInstance().getDefaultDisplay(context).get();
        DisplayAttributes attributes = display.getAttributes();
        int width = attributes.width;
        int height = attributes.height;

        ImageSource.SourceOptions sourceOptions = new ImageSource.SourceOptions();
        sourceOptions.formatHint = "image/jpeg";
        ImageSource imageSource = ImageSource.create(bitmapBytes, sourceOptions);

        ImageSource.DecodingOptions decodingOpts = new ImageSource.DecodingOptions();
        decodingOpts.sampleSize = calculateInSampleSize(imageSource.getImageInfo().size,
                width,
                height);

        PixelMap pixelMap = imageSource.createPixelmap(decodingOpts);

        imageSource.release();

        return pixelMap;
    }

    public static int calculateInSampleSize(Size resSize, int reqWidth, int reqHeight) {
        int initialInSampleSize = computeInitialSampleSize(resSize, reqWidth, reqHeight);

        int roundedInSampleSize;
        if (initialInSampleSize <= 8) {
            roundedInSampleSize = 1;
            while (roundedInSampleSize < initialInSampleSize) {
                // Shift one bit to left
                roundedInSampleSize <<= 1;
            }
        } else {
            roundedInSampleSize = (initialInSampleSize + 7) / 8 * 8;
        }

        return roundedInSampleSize;
    }

    private static int computeInitialSampleSize(Size resSize, int reqWidth, int reqHeight) {
        final double height = resSize.height;
        final double width = resSize.width;

        final long maxNumOfPixels = reqWidth * reqHeight;
        final int minSideLength = Math.min(reqHeight, reqWidth);

        int lowerBound = (maxNumOfPixels < 0) ? 1 :
                (int) Math.ceil(Math.sqrt(width * height / maxNumOfPixels));
        int upperBound = (minSideLength < 0) ? 128 :
                (int) Math.min(Math.floor(width / minSideLength),
                        Math.floor(height / minSideLength));

        if (upperBound < lowerBound) {
            // return the larger one when there is no overlapping zone.
            return lowerBound;
        }

        if (maxNumOfPixels < 0 && minSideLength < 0) {
            return 1;
        } else if (minSideLength < 0) {
            return lowerBound;
        } else {
            return upperBound;
        }
    }


}
